/*

Copyright (c) 2004-2009 Krzysztof Ostrowski. All rights reserved.

Redistribution and use in source and binary forms,
with or without modification, are permitted provided that the following conditions
are met:

1. Redistributions of source code must retain the above copyright
   notice, this list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above
   copyright notice, this list of conditions and the following
   disclaimer in the documentation and/or other materials provided
   with the distribution.

THIS SOFTWARE IS PROVIDED "AS IS" BY THE ABOVE COPYRIGHT HOLDER(S)
AND ALL OTHER CONTRIBUTORS AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDER(S) OR ANY OTHER
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.

*/

#define DEBUG_INCLUDE_INSPECTION_CODE

using System;
using System.Collections.Generic;
using System.Text;

namespace QS._qss_x_.Reflection_
{
    [QS.Fx.Printing.Printable(QS.Fx.Printing.PrintingStyle.Expanded, QS.Fx.Printing.SelectionOption.Explicit)]
    internal abstract class Class<I, C> : QS.Fx.Inspection.Inspectable, QS.Fx.Reflection.IClass<I>
        where I : QS.Fx.Reflection.IClass<I>
        where C : I 
    {
        #region Constructors

        protected Class(Library.Namespace_ _namespace, QS.Fx.Base.ID _id, ulong _incarnation, string _name, string _comment, Type _type,
            IDictionary<string, QS.Fx.Reflection.IParameter> _classparameters, IDictionary<string, QS.Fx.Reflection.IParameter> _openparameters)
        {
            this._namespace = _namespace;
            this._id = _id;
            this._incarnation = _incarnation;
            this._name = _name;
            this._comment = _comment;
            this._type = _type;
            this._classparameters = _classparameters;
            this._openparameters = _openparameters;

            this._autogeneratedid =  (this._id != null) ? (this._id.ToString() + "_" + this._incarnation.ToString()) : null;
            this._uuid = (this._id != null) ? (this._id.ToString() + "`" + this._incarnation.ToString()) : null;
        }

        #endregion

        #region Fields

        protected Library.Namespace_ _namespace;
        protected string _autogeneratedid;
        protected string _uuid;

#if DEBUG_INCLUDE_INSPECTION_CODE
        [QS.Fx.Printing.Printable("id")]
#endif
        protected QS.Fx.Base.ID _id;

#if DEBUG_INCLUDE_INSPECTION_CODE
        [QS.Fx.Printing.Printable("incarnation")]
#endif
        protected ulong _incarnation;

#if DEBUG_INCLUDE_INSPECTION_CODE
        [QS.Fx.Base.Inspectable("name")]
        [QS.Fx.Printing.Printable("name")]
#endif
        [QS.Fx.Attributes.Attribute(QS.Fx.Attributes.AttributeClasses.CLASSID_name)]
        protected string _name;

#if DEBUG_INCLUDE_INSPECTION_CODE
        [QS.Fx.Base.Inspectable("comment")]
        [QS.Fx.Printing.Printable("comment")]
#endif
        [QS.Fx.Attributes.Attribute(QS.Fx.Attributes.AttributeClasses.CLASSID_comment)]
        protected string _comment;

#if DEBUG_INCLUDE_INSPECTION_CODE
        [QS.Fx.Base.Inspectable("type")]
        [QS.Fx.Printing.Printable("type")]
#endif
        protected Type _type;

#if DEBUG_INCLUDE_INSPECTION_CODE
        [QS.Fx.Printing.Printable("class parameters")]
#endif
        protected IDictionary<string, QS.Fx.Reflection.IParameter> _classparameters;
        
#if DEBUG_INCLUDE_INSPECTION_CODE
        [QS.Fx.Printing.Printable("open parameters")]
#endif
        protected IDictionary<string, QS.Fx.Reflection.IParameter> _openparameters;

        #endregion

        #region Inspection

#if DEBUG_INCLUDE_INSPECTION_CODE

        [QS.Fx.Base.Inspectable("id")]
        [QS.Fx.Attributes.Attribute(QS.Fx.Attributes.AttributeClasses.CLASSID_id)]
        protected string __inspectable_id
        {
            get { return (_id != null) ? _id.ToString() : null; }
        }

        [QS.Fx.Base.Inspectable("class parameters")]
        protected QS._qss_e_.Inspection_.DictionaryWrapper1<string, QS.Fx.Reflection.IParameter> __inspectable_classparameters
        {
            get
            {
                return new QS._qss_e_.Inspection_.DictionaryWrapper1<string, QS.Fx.Reflection.IParameter>("class parameters", _classparameters,
                    new QS._qss_e_.Inspection_.DictionaryWrapper1<string, QS.Fx.Reflection.IParameter>.ConversionCallback(
                        delegate(string s) { return s; }));
            }
        }

        [QS.Fx.Base.Inspectable("open parameters")]
        protected QS._qss_e_.Inspection_.DictionaryWrapper1<string, QS.Fx.Reflection.IParameter> __inspectable_openparameters
        {
            get
            {
                return new QS._qss_e_.Inspection_.DictionaryWrapper1<string, QS.Fx.Reflection.IParameter>("open parameters", _openparameters,
                    new QS._qss_e_.Inspection_.DictionaryWrapper1<string, QS.Fx.Reflection.IParameter>.ConversionCallback(
                        delegate(string s) { return s; }));
            }
        }

#endif

        #endregion

        #region Abstract Methods

        protected abstract C _Instantiate(IEnumerable<QS.Fx.Reflection.IParameter> _parameters);

        #endregion

        public Library.Namespace_ _Namespace
        {
            get { return this._namespace; }
        }

        public string autogenerated_id_
        {
            get { return this._autogeneratedid; }
        }

        public string uuid_
        {
            get { return this._uuid; }
        }

        #region IClass<I> Members

        QS.Fx.Base.ID QS.Fx.Reflection.IClass<I>.ID
        {
            get { return _id; }
        }

        ulong QS.Fx.Reflection.IClass<I>.Incarnation
        {
            get { return _incarnation; }
        }

        QS.Fx.Attributes.IAttributes QS.Fx.Reflection.IClass<I>.Attributes
        {
            get { return new QS.Fx.Attributes.Attributes(this); }
        }

        IDictionary<string, QS.Fx.Reflection.IParameter> QS.Fx.Reflection.IClass<I>.ClassParameters
        {
            get { return new QS._qss_x_.Base1_.ReadonlyDictionaryOf<string, QS.Fx.Reflection.IParameter>(_classparameters); }
        }

        IDictionary<string, QS.Fx.Reflection.IParameter> QS.Fx.Reflection.IClass<I>.OpenParameters
        {
            get { return new QS._qss_x_.Base1_.ReadonlyDictionaryOf<string, QS.Fx.Reflection.IParameter>(_openparameters); }
        }

        I QS.Fx.Reflection.IClass<I>.Instantiate(IEnumerable<QS.Fx.Reflection.IParameter> _parameters)
        {
            return _Instantiate(_parameters);
        }

        Type QS.Fx.Reflection.IClass<I>.UnderlyingType
        {
            get { return Library._InstantiateParameters(this._type, this._classparameters); }
        }

        #endregion
    }
}
